import { DownOutlined, TeamOutlined } from '@ant-design/icons';
import Tree, { DataNode, EventDataNode } from 'antd/lib/tree';
import React from 'react';
import { OrganizationInfo } from 'admin/schema/Organization';
import { getOrganization } from '../../../servers/servers';
import { OrganizationHandler } from './component/OrganizationHandler';
import './style.scss';

interface OrganizationState {
  /**
   * 组织机构树
   */
  treeData: DataNode[];
  /**
   * 结构树根节点id
   */
  rootArr: number[];
}

/**
 * 职责：树渲染
 */
export default class Organization extends React.Component<{}, OrganizationState> {
  /**
   * 组织操作引用
   */
  operationRef: React.RefObject<OrganizationHandler>;

  /**
   * 树控件引用
   */
  treeRef: React.RefObject<any>;

  constructor(prop: {}) {
    super(prop);
    this.operationRef = React.createRef();
    this.treeRef = React.createRef();
    this.state = {
      treeData: [],
      rootArr: [],
    };
  }

  componentDidMount() {
    this.fetchOrganization();
  }

  componentDidUpdate() {
    this.treeRef.current.onNodeMouseEnter = (
      event: React.MouseEvent<HTMLDivElement>,
      node: EventDataNode
    ) => {
      this.handleTreeNodeChange(event, node);
    };
  }

  /**
   *  获取组织机构信息并格式化为tree控件所需的结构
   */
  private fetchOrganization(): void {
    getOrganization()
      .then(res => {
        const rootArr: number[] = [];
        const data = res.data as OrganizationInfo[];
        if (!data || !data.length) {
          return;
        }
        data.forEach(item => {
          rootArr.push(item.organizationId);
        });
        const treeData = JSON.parse(
          JSON.stringify(data)
            .replace(/organizationId/g, 'key')
            .replace(/organizationName/g, 'title')
            .replace(/subOrganizations/g, 'children')
        );
        const addIcon = (item: any) => {
          !item.children && (item.switcherIcon = <TeamOutlined />);
          if (item.children) {
            item.children.forEach((child: any) => {
              addIcon(child);
            });
          }
        };
        addIcon(treeData[0]);
        this.setState({
          treeData: treeData,
          rootArr: rootArr,
        });
      })
      .catch(error => {
        console.error(`系统异常: ${JSON.stringify(error)}`);
      });
  }

  /**
   * hover 树节点变化的函数
   * 获取事件坐标，计算弹窗出现的位置
   */
  private handleTreeNodeChange(event: React.MouseEvent<HTMLDivElement>, node: EventDataNode) {
    event.persist();
    const target = event.nativeEvent.relatedTarget as HTMLDivElement;
    if (!target) {
      return;
    }
    const x = target.getBoundingClientRect().left + target.offsetWidth + 15;
    const y = target.getBoundingClientRect().top + target.offsetHeight / 2 - 60;
    this.operationRef.current?.show({
      position: [x, y],
      caption: node.title as string,
      key: node.key,
      isRoot: this.state.rootArr.includes(parseInt(node.key as string)),
    });
  }

  /**
   * 隐藏弹窗函数
   * 当鼠标位置在整个treedom下的时候，隐藏弹窗
   */
  private onLeaveTree(e: React.MouseEvent<HTMLDivElement, MouseEvent>) {
    const treeDom = document.querySelector('.ant-tree') as HTMLDivElement;
    const height = treeDom.offsetHeight + treeDom.offsetTop;
    if (e.nativeEvent.clientY > height + 150) {
      this.operationRef.current?.hide();
    }
  }

  render() {
    const { treeData, rootArr } = this.state;
    const { operationRef, treeRef } = this;

    return (
      <>
        <div className="organization-mgr-title">
          组织机构树
          <span style={{ color: 'red' }}>（鼠标放在组织机构上可以操作组织）</span>
        </div>
        <div
          className="organization-mgr"
          onMouseMove={e => {
            this.onLeaveTree(e);
          }}
        >
          <Tree
            autoExpandParent={true}
            // defaultExpandAll={true}
            defaultExpandedKeys={[rootArr[0]]}
            ref={treeRef}
            treeData={treeData}
            switcherIcon={<DownOutlined />}
            showLine
            showIcon={false}
          />
          <OrganizationHandler
            ref={operationRef}
            refresh={() => {
              this.fetchOrganization();
            }}
          />
        </div>
      </>
    );
  }
}
